home *** CD-ROM | disk | FTP | other *** search
/ Best Tools for JAVA / Best Tools for JAVA.iso / JAVA_ALL / IDE / SUBARTIC / SUB_ARCT / LIB / ONELINE_.JAV < prev    next >
Encoding:
Text File  |  1996-10-04  |  19.8 KB  |  566 lines

  1. package sub_arctic.lib;
  2.  
  3. import sub_arctic.input.text_acceptor;
  4. import sub_arctic.input.pressable;
  5. import sub_arctic.input.simple_draggable;
  6. import sub_arctic.input.event;
  7. import sub_arctic.input.focus_dispatch_agent;
  8. import sub_arctic.input.int_holder;
  9.  
  10. import sub_arctic.lib.sub_arctic_error;
  11.  
  12. import java.awt.Font;
  13.  
  14. /** 
  15.  * Single line text edit box.  This class allows entry and editing of a 
  16.  *  single line of text.  The text is maintained with a selection or entry
  17.  *  point.  Selection positions in strings refer to the spaces before the 
  18.  *  characters (numbered from 0).  So for example a selection from 0 to 0 
  19.  *  places the cursor before the first character (the character at index 0) 
  20.  *  while a selection from 1 to 2 selects the second character 
  21.  * (the character at index 1).
  22.  * 
  23.  * @author Scott Hudson 
  24.  */
  25. public class oneline_text_edit extends oneline_text_display 
  26.   implements text_acceptor, pressable, simple_draggable {
  27.  
  28.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  29.  
  30.   // things left to do:
  31.   //   draw non-focus objects differently than the focus
  32.   //   think about support for field tabbing (subclass?)
  33.  
  34.   /** 
  35.    * Full constructor with explicit width 
  36.    * @param int    xv       x coordinate of this interactor.
  37.    * @param int    yv       y coordinate of this interactor.
  38.    * @param int    wv       width of this interactor.
  39.    * @param String init_str the initial string.
  40.    * @param Font   fnt      the font to use for this interactor.
  41.    * @param boolean boxed true if you want this interactor to have a box 
  42.    *                      around it.
  43.    */
  44.   public oneline_text_edit(
  45.     int              xv, 
  46.     int              yv, 
  47.     int              wv,
  48.     String           init_str, 
  49.     Font             fnt, 
  50.     boolean          boxed)
  51.     {
  52.       super(xv,yv,wv,init_str,fnt,boxed);
  53.     }
  54.  
  55.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  56.  
  57.   /** 
  58.    * Full constructor where width is determined by initial string 
  59.    * @param int     xv       x coordinate of this interactor.
  60.    * @param int     yv       y coordinate of this interactor.
  61.    * @param String  init_str the initial string.
  62.    * @param Font    fnt      the font to use for this interactor.
  63.    * @param boolean boxed    true if you want this interactor to have a box 
  64.    *                      around it.
  65.    */
  66.   public oneline_text_edit( 
  67.     int              xv, 
  68.     int              yv, 
  69.     String           init_str, 
  70.     Font             fnt, 
  71.     boolean          boxed)
  72.     {
  73.       super(xv,yv,init_str,fnt,boxed);
  74.     }
  75.  
  76.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  77.  
  78.   /** 
  79.    * Constructor with default font and boxed status 
  80.    * @param int     xv       x coordinate of this interactor.
  81.    * @param int     yv       y coordinate of this interactor.
  82.    * @param String  init_str the initial string.
  83.    * @param Font    fnt      the font to use for this interactor.
  84.    * @param boolean boxed    true if you want this interactor to have a box 
  85.    *                         around it.
  86.    */
  87.   public oneline_text_edit(
  88.     int              xv, 
  89.     int              yv, 
  90.     String           init_str)
  91.     {
  92.       super(xv,yv,init_str);
  93.     }
  94.  
  95.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  96.  
  97.   /** 
  98.    * Constructor with default font and boxed status; we also assume
  99.    * you are going to set the x and y coordinate by other means.
  100.    *
  101.    * @param int     xv       x coordinate of this interactor.
  102.    * @param int     yv       y coordinate of this interactor.
  103.    * @param String  init_str the initial string.
  104.    * @param Font    fnt      the font to use for this interactor.
  105.    * @param boolean boxed    true if you want this interactor to have a box 
  106.    *                         around it.
  107.    */
  108.   public oneline_text_edit(String init_str)
  109.     {
  110.       super(init_str);
  111.     }
  112.  
  113.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  114.  
  115.   /** 
  116.    * Replace the area of the current selection with the given string.  The
  117.    *  selection is set to a single point after the new text.  Since the 
  118.    *  the replacement string can be empty, this can be used to delete the 
  119.    *  selection.  
  120.    * 
  121.    * @param String with_str the string to replace with.
  122.    */
  123.   public void replace_selection(String with_str)
  124.     {
  125.       String before, after;
  126.       int    pos;
  127.  
  128.       /* if they pass a null treat that as an empty string */
  129.       if (with_str == null) with_str = "";
  130.  
  131.       /* if there is no selection, bail out early */
  132.       if (start_of_selection() == NO_SELECTION) return;
  133.  
  134.       /* extract the pieces before and after the selection */
  135.       before = text().substring(0,start_of_selection());
  136.       after  = text().substring(end_of_selection(), text().length());
  137.  
  138.       /* concatenate a new string */
  139.       set_text(before + with_str + after);
  140.  
  141.       /* set the selection to a point right after the new text */
  142.       pos = before.length() + with_str.length();
  143.       set_selection(pos,pos);
  144.     }
  145.  
  146.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  147.  
  148.   /** 
  149.    * Delete the character before the current selection (backing the selection
  150.    * up one character).  If there is no selection or the selection starts at
  151.    * the beginning of the string, nothing happens.  
  152.    */
  153.   public void delete_a_char()
  154.     {
  155.       String before, after;
  156.  
  157.       /* if there is no selection or selection is at beginning, bail now */
  158.       if (start_of_selection() == NO_SELECTION || start_of_selection() == 0) 
  159.         return;
  160.  
  161.       /* extract the piece before selection, less one character */
  162.       before = text().substring(0,start_of_selection()-1);
  163.  
  164.       /* extract the piece after the start of the selection */
  165.       after = text().substring(start_of_selection(),text().length());
  166.  
  167.       /* replace the text and move the selection over */
  168.       set_text(before+after);
  169.       set_selection(start_of_selection()-1, end_of_selection()-1);
  170.       ensure_inside(start_of_selection()-1);
  171.     }
  172.  
  173.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  174.  
  175.   /** 
  176.    * Map an x position in local coordinates into a text string position. 
  177.    * @return int the position of the point in the string (in characters)
  178.    * @param int xpos the x position to transform (in pixels).
  179.    */
  180.   public int char_pos_of(int xpos)
  181.     {
  182.       int len, front, mid, back, dist;
  183.       char[] the_text;
  184.  
  185.       /* first take off x margin and adjustment */
  186.       xpos -= _h_spacing + x_adjust();
  187.  
  188.       /* take care of positions before start */
  189.       if (xpos < 0) return 0;
  190.  
  191.       /* extract character array from string */
  192.       len = text().length();
  193.       the_text = new char[len];
  194.       text().getChars(0,len,the_text,0);
  195.  
  196.       /* binary search to find the text position before the insert point */
  197.       front = 0; 
  198.       back = len;
  199.       do {
  200.     mid = (front + back)/2;
  201.     dist = xpos - _metric.charsWidth(the_text, 0, mid);
  202.     if (dist > 0)
  203.       front = mid;
  204.     else if (dist == 0)
  205.       return mid;
  206.     else
  207.       back = mid; 
  208.       } while (front+1 < back);
  209.  
  210.       /* if we are at the end just take that */
  211.       if (mid == len) return front;
  212.  
  213.       /* now see if we are more than 1/2 way into the final character */
  214.       if (Math.abs(xpos - _metric.charsWidth(the_text, 0, front)) > 
  215.           Math.abs(xpos-_metric.charsWidth(the_text, 0, front+1)))
  216.     return front + 1;
  217.       else
  218.     return front;
  219.     }
  220.  
  221.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  222.   /* text_acceptor (input) methods */
  223.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  224.  
  225.   /** 
  226.    * Accept input that signifies that object is new text focus and will
  227.    * receive subsequent text input.  Returns true if the object accepts the
  228.    * focus.   
  229.    * @param event  evt       the start of the text entry event.
  230.    * @param Object user_info the object passed to the agent when we went into 
  231.    *                         the focus set.
  232.    * @return boolean true if we consumed the event, which we always do.
  233.    */
  234.   public boolean start_text_entry(event evt, Object user_info)
  235.     {
  236.       return true;
  237.     }
  238.  
  239.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  240.  
  241.   /** 
  242.    * Pre-filter a character before providing it is actually provided as input.
  243.    * This routine gets called to allow the object to modify the character 
  244.    * before it is passed to new_char().  Input to the method is the ordinal 
  245.    * value of the input character in question along with the modifier mask 
  246.    * associated with it.  Output should either be the ordinal value of a  
  247.    * character or a specific negative value signifying one of several special 
  248.    * actions.  <p>
  249.    *
  250.    * This routine can be used by subclasses to do a translation (e.g. to all 
  251.    * lower case) or to filter out unwanted characters (e.g. everything except 
  252.    * decimal digits). Filtering is done by returning the  special value 
  253.    * DISCARD_CHAR (= -1), which signifies that the character is not to be 
  254.    * passed to new_char().  Translation is done by returning the ordinal value 
  255.    * of the translated character.  In addition, the value CLOSURE_ACTION_CHAR 
  256.    * can be returned to indicate that the action_char() method should be 
  257.    * invoked instead of new_char().  This is typically done for end of line 
  258.    * characters that signify completion of an entry.  All modifications to the 
  259.    * character are considered local to this  object and do not change how the 
  260.    * character might be delivered to another object. <p>
  261.    *
  262.    * This routine is not called for cursor movement or other special keys 
  263.    * (which are dispatched with special_key()), or characters classified  
  264.    * as edit keys (e.g. to delete a character or line).  The text input 
  265.    * dispatch agent class (text_agent) provides several standard filters 
  266.    * that can be  called for common operations. 
  267.    * 
  268.    * @param int input_char the char that was hit.
  269.    * @param int modifiers state of the modifier keys.
  270.    * @return int the character to insert or a special value (DISCARD_CHAR or 
  271.    *             CLOSURE_ACTION_CHAR).
  272.    */
  273.   public int char_filter(int input_char, int modifiers)
  274.     {
  275.       /* here we do no filtering and no translation */
  276.       return input_char;
  277.     }
  278.  
  279.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  280.  
  281.   /** 
  282.    * Accept input for a single character.  Returns true if the object
  283.    * consumes the character. 
  284.    *
  285.    * @param event  evt       the input event (normally a keypress) .
  286.    * @param Object user_info the object passed to the agent when this object 
  287.    *                         entered the focus set.
  288.    * @boolean true if we accepted this character.
  289.    */
  290.   public boolean new_char(event evt, char ch, Object user_info)
  291.     {
  292.       /* if we have no selection, make one at the end */
  293.       if (start_of_selection() == NO_SELECTION)
  294.     set_selection(SELECT_END,SELECT_END);
  295.  
  296.       /* replace selection with the char */
  297.       replace_selection(String.valueOf(ch));
  298.  
  299.       return true;
  300.     }
  301.  
  302.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  303.  
  304.   /** 
  305.    * Accept input for a character that has been classified as a closure
  306.    * action (by returning CLOSURE_ACTION_CHAR from char_filter).  Returns 
  307.    * true if the object consumes the character.
  308.    * 
  309.    * @param event  evt       the input event (normally a keypress). 
  310.    * @param char   ch        the action character in question.
  311.    * @param Object user_info the object passed to the agent when this object 
  312.    *                         entered the focus set.
  313.    * @boolean true if we handled this character.
  314.    */
  315.   public boolean action_char(event evt, char ch, Object user_info)
  316.     {
  317.       /* Here we consume, but ignore closure characters */
  318.       return true;
  319.     }
  320.  
  321.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  322.  
  323.   /** 
  324.    * Accept input for a character signifying a delete.  Returns true if the
  325.    * object consumes the input.  
  326.    *
  327.    * @param event  evt       the input event (normally a keypress).
  328.    * @param Object user_info the object passed to the agent when this object 
  329.    *                         entered the focus set.
  330.    * @boolean true if we handled this delete character.
  331.    */
  332.   public boolean delete_char(event evt, Object user_info)
  333.     {
  334.       /* if we have no selection, we do nothing */
  335.       if (start_of_selection() == NO_SELECTION) 
  336.     return true;
  337.  
  338.       /* if we have a point selection delete back from it */
  339.       if (start_of_selection() == end_of_selection())
  340.         delete_a_char();
  341.       /* otherwise replace selection with an empty string */
  342.       else
  343.     replace_selection("");
  344.  
  345.       return true;
  346.     }
  347.  
  348.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  349.  
  350.   /** 
  351.    * Accept input for a character signifying a line kill.  Returns true if
  352.    * the object consumes the input.  Currently a ^U ('\025') is treated as
  353.    * a line kill. This behavior can be changed via the text input dispatch 
  354.    * agent. (Unfortunately, AWT does not currently provide a way to determine 
  355.    * the user's edit character preferences, so this is the best we can do.)
  356.    * 
  357.    * @param event  evt       the input event (normally a keypress).
  358.    * @param Object user_info the object passed to the agent when this object 
  359.    *                         entered the focus set.
  360.    * @boolean true if we handled this line kill.
  361.    */
  362.   public boolean line_kill(event evt, Object user_info)
  363.     {
  364.       /* select the whole text, then remove it */
  365.       set_selection(0, SELECT_END);
  366.       replace_selection("");
  367.  
  368.       return true;
  369.     }
  370.  
  371.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  372.  
  373.   /** Accept input for a key press signifying a special key (corresponding
  374.    *  to KEY_ACTION events).  Values passed here are from the key field of the
  375.    *  events.  These include: DOWN, END, F1, ..., F12, HOME, LEFT, PGDN, PGUP, 
  376.    *  RIGHT, and UP.  Returns true if the object consumes the event.
  377.    *
  378.    * @param event  evt       the input event (normally a key_action event).  
  379.    * @param int    key_code  the special key in question.
  380.    * @param Object user_info the object passed to the agent when this object 
  381.    *                         entered the focus set.
  382.    * @boolean true if we handled this special key.
  383.    */
  384.   public boolean special_key(event evt, int key_code, Object user_info)
  385.     {
  386.  
  387.       /* handle LEFT and RIGHT only */
  388.       if (key_code == event.LEFT)
  389.     {
  390.       /* if we have no selection, we are done */
  391.       if (start_of_selection() == NO_SELECTION) return false;
  392.  
  393.       /* if we have a point selection, just move */
  394.       if (start_of_selection() == end_of_selection())
  395.         {
  396.           if (start_of_selection() != 0)
  397.             set_selection(start_of_selection()-1, start_of_selection()-1);
  398.         }
  399.       /* otherwise go to a point selection at the left */
  400.       else
  401.         set_selection(start_of_selection(), start_of_selection());
  402.  
  403.           return true;
  404.     }
  405.  
  406.       if (key_code == event.RIGHT)
  407.     {
  408.       /* if we have no selection, we are done */
  409.       if (start_of_selection() == NO_SELECTION) return false;
  410.  
  411.       /* if we have a point selection, just move */
  412.       if (start_of_selection() == end_of_selection())
  413.         set_selection(start_of_selection()+1, start_of_selection()+1);
  414.       /* otherwise go to a point selection at the right */
  415.       else
  416.         set_selection(end_of_selection(), end_of_selection());
  417.  
  418.           return true;
  419.     }
  420.  
  421.       /* we don't want anything else */
  422.       return false;
  423.     }
  424.  
  425.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  426.  
  427.   /** 
  428.    * Dispatch input indicating that text input is over (e.g. the text focus
  429.    * has moved elsewhere.  Returns true if the object consumes the input.
  430.    *
  431.    * @param event  evt       the input event.
  432.    * @param Object user_info the object passed to the agent when this object 
  433.    *                         entered the focus set.
  434.    * @boolean true if we handled this event.
  435.    */
  436.   public boolean end_text_entry(event evt, Object user_info)
  437.     {
  438.       /* here we do nothing */
  439.       return true;
  440.  
  441.       // later we need to go to another highlight style
  442.     }
  443.  
  444.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  445.   /* pressable (input) methods */
  446.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  447.  
  448.   /** 
  449.    * Accept mouse button press input to the object.  Return true is event 
  450.    *  was consumed. 
  451.    *
  452.    * @param event  evt       the input event.
  453.    * @param Object user_info the object passed to the agent when this object 
  454.    *                         entered the focus set.
  455.    * @boolean true if we handled this event.
  456.    */
  457.   public boolean press(event evt, Object user_info)
  458.     {
  459.       /* make us both the text and drag focus */
  460.       manager.text_focus.set_focus_to(this, evt, user_info);
  461.       manager.simple_drag_focus.set_focus_to(this, evt, new int_holder(0));
  462.       return true;
  463.     }
  464.  
  465.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  466.  
  467.   /** 
  468.    * Companion method to press() needed to finish pressable.  Here we never
  469.    * consume the event. 
  470.    *
  471.    * @param event  evt       the input event.
  472.    * @param Object user_info the object passed to the agent when this object 
  473.    *                         entered the focus set.
  474.    * @boolean true if we handled this event.
  475.    */
  476.   public boolean release(event evt, Object user_info)
  477.     {
  478.       return false;
  479.     }
  480.  
  481.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  482.   /* simple_draggable (input) methods */
  483.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  484.  
  485.   /** 
  486.    * Accept the start of a drag to the object.  
  487.    *
  488.    * @param event  evt       the input event.
  489.    * @param Object user_info the object passed to the agent when this object 
  490.    *                         entered the focus set.
  491.    * @boolean true if we handled this event.
  492.    */
  493.   public boolean drag_start(event evt, Object user_info)
  494.     {
  495.      int pos;
  496.  
  497.       /* establish the start of selection where this event was */
  498.       pos = char_pos_of(evt.local_x());
  499.       set_selection(pos,pos);
  500.  
  501.       /* remember the start position */
  502.       ((int_holder)user_info).value = pos;
  503.  
  504.       return true;
  505.  
  506.       //later need to handle "extend" case (w/ shift down)
  507.     }
  508.  
  509.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  510.  
  511.   /** 
  512.    * Accept a movement during a drag.  
  513.    *
  514.    * @param event  evt       the input event.
  515.    * @param Object user_info the object passed to the agent when this object 
  516.    *                         entered the focus set.
  517.    * @boolean true if we handled this event
  518.    */
  519.   public boolean drag_feedback(event evt, Object user_info)
  520.     {
  521.       int pos;
  522.  
  523.       /* set end of selection here (we rely on set_selection() to flip) */
  524.       pos = char_pos_of(evt.local_x());
  525.       set_selection(((int_holder)user_info).value, pos);
  526.       ensure_inside(pos);
  527.  
  528.       return true;
  529.     }
  530.  
  531.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  532.  
  533.   /** 
  534.    * Accept input corresponding to the end of a drag.  
  535.    *
  536.    * @param event  evt       the input event.
  537.    * @param Object user_info the object passed to the agent when this 
  538.    *                         object entered the focus set.
  539.    * @boolean true if we handled this event.
  540.    */
  541.   public boolean drag_end(event evt, Object user_info)
  542.     {
  543.       /* let drag_feedback do the work */
  544.       return drag_feedback(evt, user_info);
  545.     }
  546.  
  547.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  548. }
  549.  
  550. /*=========================== COPYRIGHT NOTICE ===========================
  551.  
  552. This file is part of the subArctic user interface toolkit.
  553.  
  554. Copyright (c) 1996 Scott Hudson and Ian Smith
  555. All rights reserved.
  556.  
  557. The subArctic system is freely available for most uses under the terms
  558. and conditions described in 
  559.   http://www.cc.gatech.edu/gvu/ui/sub_arctic/sub_arctic/doc/usage.html 
  560. and appearing in full in the lib/interactor.java source file.
  561.  
  562. The current release and additional information about this software can be 
  563. found starting at: http://www.cc.gatech.edu/gvu/ui/sub_arctic/
  564.  
  565. ========================================================================*/
  566.